package com.mcxx.modules.miniSalvation.order.service.read;

import com.mcxx.common.exception.BizException;
import com.mcxx.modules.miniSalvation.order.dao.read.NoticeBoardDetailReadDao;
import com.mcxx.modules.miniSalvation.order.dao.read.NoticeBoardReadDao;
import com.mcxx.modules.base.utils.QueryParamUtil;
import com.mcxx.modules.miniSalvation.order.dto.OrderDTO;
import com.mcxx.modules.miniSalvation.order.dto.OrderListForChoiceDTO;
import com.mcxx.modules.miniSalvation.order.dto.NoticeBoardDTO;
import com.mcxx.modules.miniSalvation.order.dto.NoticeBoardDetailDTO;
import com.mcxx.modules.miniSalvation.order.param.NoticeBoardSearchOrderParam;
import com.mcxx.modules.miniSalvation.order.param.NoticeBoardParam;
import com.mcxx.modules.miniSalvation.order.param.OrderListSearchParam;
import com.mcxx.modules.temporary.order.service.read.TmpOrderCertReadService;
import com.mcxx.util.*;
import com.yinhai.ta404.core.restservice.requestbean.PageParam;
import com.yinhai.ta404.core.restservice.resultbean.Page;
import com.yinhai.ta404.core.security.vo.UserAccountVo;
import com.yinhai.ta404.core.service.BaseService;
import com.yinhai.ta404.core.transaction.annotation.TaTransactional;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.mcxx.redis.client.RedisClusterUtils;

import java.util.*;
import java.util.stream.Collectors;


@Service("noticeBoardReadService")
@TaTransactional(readOnly = true)
public class NoticeBoardReadService extends BaseService {

    private final static Logger log = LoggerFactory.getLogger(NoticeBoardReadService.class);
    @Autowired
    private NoticeBoardReadDao noticeBoardReadDao;
    @Autowired
    private NoticeBoardDetailReadDao noticeBoardDetailReadDao;

    @Autowired
    private RedisClusterUtils redisClusterUtils;
    @Autowired
    private TmpOrderCertReadService tmpOrderCertReadService;
    @Autowired
    private OrderCertReadService orderCertReadService;


    public Page findPage(NoticeBoardParam param, PageParam pageParam, UserAccountVo userAccountVo) {

        QueryParamUtil.setBaseParamValue(param, userAccountVo);


        noticeBoardReadDao.beginPager(pageParam);
        List<NoticeBoardDTO> list = noticeBoardReadDao.queryList(param);

        return noticeBoardReadDao.endPager(list);
    }


    public Map<String, List<String>> getBatchNoByStateStartDate(List<String> batchNoList, String state) {
        Map<String, List<String>> rstMap = new HashMap<>();

        List<String> yesOperationBatchNoList = noticeBoardReadDao.getBatchNoByStateStartDate(batchNoList, state);
        if (yesOperationBatchNoList.size() == 0) {

            rstMap.put("noOperation", batchNoList);
            return rstMap;
        }
        if (yesOperationBatchNoList.size() == batchNoList.size()) {

            rstMap.put("yesOperation", batchNoList);
            return rstMap;
        }

        List<String> noOperationBatchNoList = batchNoList.stream().filter(batchNo -> yesOperationBatchNoList.contains(batchNo) == false).collect(Collectors.toList());

        rstMap.put("yesOperation", yesOperationBatchNoList);
        rstMap.put("noOperation", noOperationBatchNoList);

        return rstMap;
    }


    public Map<String, List<String>> getBatchNoByStateStartDate(List<String> batchNoList, List<String> stateList, String isTemp) {
        Map<String, List<String>> rstMap = new HashMap<>();

        List<String> yesOperationBatchNoList = noticeBoardReadDao.getBatchNoByStateStartDates(batchNoList, stateList, isTemp);
        if (yesOperationBatchNoList.size() == 0) {

            rstMap.put("noOperation", batchNoList);
            return rstMap;
        }
        if (yesOperationBatchNoList.size() == batchNoList.size()) {

            rstMap.put("yesOperation", batchNoList);
            return rstMap;
        }

        List<String> noOperationBatchNoList = batchNoList.stream().filter(batchNo -> yesOperationBatchNoList.contains(batchNo) == false).collect(Collectors.toList());

        rstMap.put("yesOperation", yesOperationBatchNoList);
        rstMap.put("noOperation", noOperationBatchNoList);

        return rstMap;
    }


    public Integer checkByNoAndStartDate(String batchId) {

        return noticeBoardReadDao.cntByIdAndStartDate(batchId);
    }


    public NoticeBoardDTO queryByBatchId(String batchId) {
        return noticeBoardReadDao.queryByBatchId(batchId);
    }


    public Map<String, Object> printNoticeBoardTown(String batchId) {
        Map<String, Object> rstMap = new HashMap<>();

        NoticeBoardDTO noticeBoard = noticeBoardReadDao.queryByBatchId(batchId);

        long allLimitDay = DateUtil.dateDiff(noticeBoard.getStartDate(), noticeBoard.getEndDate()) + 1;
        noticeBoard.setTimeLimit(allLimitDay + "");
        rstMap.put("noticeBoard", noticeBoard);


        OrderListSearchParam param = new OrderListSearchParam();
        param.setBatchId(batchId);
        List<NoticeBoardDetailDTO> noticeBoardDetailList = noticeBoardDetailReadDao.queryObjectByBatchId(param);
        rstMap.put("noticeBoardDetailList", noticeBoardDetailList);


        return rstMap;
    }


    public Page findEntrustTodo(NoticeBoardParam param, PageParam pageParam, UserAccountVo userAccount) {

        QueryParamUtil.setBaseParamValue(param, userAccount);


        param.setUserAreaLevel("3");

        noticeBoardReadDao.beginPager(pageParam);
        List<NoticeBoardDTO> list = noticeBoardReadDao.queryEntrustTodo(param);
        return noticeBoardReadDao.endPager(list);
    }


    public Page findEntrustFinish(NoticeBoardParam param, PageParam pageParam, UserAccountVo userAccount) {

        QueryParamUtil.setBaseParamValue(param, userAccount);

        param.setOrgId(userAccount.getOrgId());

        param.setUserAreaLevel("3");

        noticeBoardReadDao.beginPager(pageParam);
        List<NoticeBoardDTO> list = noticeBoardReadDao.queryEntrustFinish(param);

        for (NoticeBoardDTO entity : list) {

            StringBuffer timeLimit = new StringBuffer();
            timeLimit.append("7");
            entity.setTimeLimit(timeLimit.toString());
        }
        return noticeBoardReadDao.endPager(list);
    }


    public List<NoticeBoardDetailDTO> printNoticeBoardCounty(String batchId) {




        OrderListSearchParam param = new OrderListSearchParam();
        param.setBatchId(batchId);
        List<NoticeBoardDetailDTO> noticeBoardDetailList = noticeBoardDetailReadDao.queryObjectByBatchId(param);

        return noticeBoardDetailList;
    }


    public int checkBatchStateByConfirm(String batchNo) {
        return noticeBoardReadDao.checkConfirm(batchNo);
    }



    public Map<String, List<String>> stopBatchCheckState(List<String> batchNoList, List<String> stateList) {
        Map<String, List<String>> rstMap = new HashMap<>();

        List<String> noOperationBatchNoList = noticeBoardReadDao.queryNoByNoAndStatuss(batchNoList, stateList);
        if (noOperationBatchNoList.size() == batchNoList.size()) {

            rstMap.put("noOperation", batchNoList);
            return rstMap;
        }
        if (noOperationBatchNoList.size() == 0) {

            rstMap.put("yesOperation", batchNoList);
            return rstMap;
        }

        List<String> yesOperationBatchNoList = batchNoList.stream().filter(batchNo -> noOperationBatchNoList.contains(batchNo) == false).collect(Collectors.toList());

        rstMap.put("yesOperation", yesOperationBatchNoList);
        rstMap.put("noOperation", noOperationBatchNoList);

        return rstMap;
    }


    public List<NoticeBoardDetailDTO> getBatchOrderInfo(String startDate, String state) {
        return noticeBoardDetailReadDao.getBatchOrderInfo(startDate, state);
    }


    public Page queryNoFormulaListPage(NoticeBoardSearchOrderParam orderListSearch, PageParam pageParam, UserAccountVo userAccountVo) {

        QueryParamUtil.setBaseParamValue(orderListSearch, userAccountVo);
        orderListSearch.setBizState(Constant.BizStateTmp.WAIT_NOTICE_BOARD);
        if (Constant.UserLevel.COUNTY.equals(userAccountVo.getAreaLevel())) {
            orderListSearch.setBizState(Constant.BizStateTmp.COUNTY_WAIT_NOTICE_BOARD);
        }

        noticeBoardReadDao.beginPager(pageParam);
        List<OrderListForChoiceDTO> list = noticeBoardReadDao.queryNoFormulaList(orderListSearch);

        return noticeBoardReadDao.endPager(list);
    }


    public Object queryNoFormulaList(NoticeBoardSearchOrderParam orderListSearch, UserAccountVo userAccountVo, int type) {

        QueryParamUtil.setBaseParamValue(orderListSearch, userAccountVo);
        if (Constant.BusinessCode.LINSHI.equals(orderListSearch.getBusinessType())) {
            orderListSearch.setBizState(Constant.BizStateTmp.WAIT_NOTICE_BOARD);
            if (Constant.UserLevel.COUNTY.equals(userAccountVo.getAreaLevel())) {
                orderListSearch.setBizState(Constant.BizStateTmp.COUNTY_WAIT_NOTICE_BOARD);
            }
        } else {
            orderListSearch.setBizState(Constant.BizStateNew.WAIT_NOTICE_BOARD);
            if (Constant.UserLevel.COUNTY.equals(userAccountVo.getAreaLevel())) {
                orderListSearch.setBizState(Constant.BizStateNew.APPROVE_YES);
                orderListSearch.setBizState(Constant.BizStateNew.COUNTRY_WAIT_NOTICE_BOARD);
            }
        }
        if(Constant.PayWay.ALL.equals(orderListSearch.getPayWay())){
            orderListSearch.setPayWay("");
        }
        Integer integer = noticeBoardReadDao.queryNoFormulaListB(orderListSearch);

        if (type == 1 && integer > 0) {

            String redisKey = userAccountVo.getAreaCode() + orderListSearch.getBatchId() + orderListSearch.getPayWay();
            if (Constant.UserLevel.COUNTY.equals(userAccountVo.getAreaLevel())) {

                redisKey = orderListSearch.getAreaCode() + "000" + orderListSearch.getBatchId() + orderListSearch.getPayWay();
            }
            log.info("redisKey:"+redisKey);
            List<OrderListForChoiceDTO> list = new ArrayList<>();
            Map<String, OrderListForChoiceDTO> map = redisClusterUtils.hmget(redisKey);
            if (null != map) {
                map = map.entrySet().stream()
                        .filter((e) -> checkValue(e.getValue(), orderListSearch))
                        .collect(Collectors.toMap(
                                (e) -> (String) e.getKey(),
                                (e) -> e.getValue()
                        ));
                if (null != map) {
                    list = new ArrayList(map.values());
                }
            } else {
                list = noticeBoardReadDao.queryNoFormulaList(orderListSearch);
                if (CollectionUtils.isNotEmpty(list)) {
                    Map<String, OrderListForChoiceDTO> collect = list.stream().collect(Collectors.toMap(OrderListForChoiceDTO::getOrderId, noFormula -> noFormula));
                    redisClusterUtils.hmset(redisKey, collect, 60 * 60);
                }
            }
        }
        return integer;
    }


    private static boolean checkValue(OrderListForChoiceDTO e, NoticeBoardSearchOrderParam param) {
        String areaCode = param.getAddressCode();
        String name = param.getName();
        String idCard = param.getIdcard();
        if (StringUtils.isNotBlank(areaCode) && StringUtils.isNotBlank(name) && StringUtils.isNotBlank(idCard)) {
            if (e.getAreaCode().contains(areaCode) &&
                    e.getName().contains(name) &&
                    e.getIdcard().contains(idCard)) {
                return true;
            }
        } else if (StringUtils.isNotBlank(areaCode) && StringUtils.isNotBlank(name)) {
            if (e.getAreaCode().contains(areaCode) &&
                    e.getName().contains(name)) {
                return true;
            }
        } else if (StringUtils.isNotBlank(areaCode) && StringUtils.isNotBlank(idCard)) {
            if (e.getAreaCode().contains(areaCode) &&
                    e.getIdcard().contains(idCard)) {
                return true;
            }
        } else if (StringUtils.isNotBlank(name) && StringUtils.isNotBlank(idCard)) {
            if (e.getName().contains(name) &&
                    e.getIdcard().contains(idCard)) {
                return true;
            }
        } else if (StringUtils.isNotBlank(areaCode)) {
            if (e.getAreaCode().contains(areaCode)) {
                return true;
            }
        } else if (StringUtils.isNotBlank(name)) {
            if (e.getName().contains(name)) {
                return true;
            }
        } else if (StringUtils.isNotBlank(idCard)) {
            if (e.getIdcard().contains(idCard)) {
                return true;
            }
        }
        if (StringUtils.isBlank(areaCode) && StringUtils.isBlank(name) && StringUtils.isBlank(idCard)) {
            return true;
        }
        return false;
    }


    public List<OrderDTO> getOrderStateAndVersions(String batchId, String tableTop) {
        return noticeBoardReadDao.getOrderStateAndVersions(batchId, tableTop);
    }


    public List<NoticeBoardDTO> queryNoticeNotFinish() {
        return noticeBoardReadDao.queryNoticeNotFinish();
    }


    public List<NoticeBoardDTO> queryUserByNoticeOrgId(List<String> idsList) {
        return noticeBoardReadDao.queryUserByNoticeOrgId(idsList);
    }


    public NoticeBoardDTO queryIsNoticeIng(NoticeBoardDetailDTO dto) {
        return noticeBoardReadDao.queryIsNoticeIng(dto);
    }


    public List<NoticeBoardDTO> queryNoticeAreaByParId(String parentId) {
        return noticeBoardReadDao.queryNoticeAreaByParId(parentId);
    }


    public int checkNoticeOpera(String batchId, String batchNo, String type) {
        if (Constant.NoticeBoardState.COMPLETE.equals(type)) {

            int rst = tmpOrderCertReadService.cntNoticeCertNum(batchId);
            if (rst <= 0) {
                List<NoticeBoardDTO> noticeBoardDTOS = orderCertReadService.cntNoticesCertNum(new ArrayList<String>() {{
                    add(batchNo);
                }});
                if (CollectionUtils.isNotEmpty(noticeBoardDTOS)) {
                    rst = noticeBoardDTOS.get(0).getCertNum();
                }
            }
            if (rst <= 0) {
                throw new BizException(FailureCode.ERR_20081);
            }
        }

        String state = Constant.NoticeBoardState.operatMap.get(type);
        return noticeBoardReadDao.checkNoticeOpera(batchId, state);
    }

    public int selectNoticeDate(String batchNo){
        return noticeBoardReadDao.selectNoticeDate(batchNo);
    }

    public NoticeBoardDTO getBatchById(String batchId) {
        return noticeBoardReadDao.queryByBatchId(batchId);
    }


    public List<NoticeBoardDTO> queryUserByArea(String areaCode) {
        return noticeBoardReadDao.queryUserByArea(areaCode);
    }
}
